Viff - a tool for visual diffing and merging

The visual diff
Why use viff?
Running viff
viff options
The viff display
viff commands
Compiling viff
Remarks
About the author

The visual diff

viff is a freeware tool for comparing and merging files. It will run on Unix, DOS, and in DOS-boxes under all flavors of Microsoft Windows. It is character based, command line oriented, and keyboard controlled. It was created in january 1994 to allow several programmers on a large software project to work simultaneously on each their copy of the many hundred files of the project by offering a powerful, fast, and solid way to merge their changes. In that and other projects, viff soon became indispensable.

The power of viff is that

This document is the manual for viff. It explains both the options for invoking viff and the commands available inside it.

Back to top

Why use viff?

In program development teams, several programmers work on the same set of source files. There are basically two ways this can be coordinated:

  1. A source code control system is used (SCCS, RCS, SourceSafe, CVS, etc). Each programmer must check out the desired files, work on them, and finally check them back in again. Meanwhile they are locked and no one else can make changes to them.
  2. Each programmer works on a copy of the source files. Any changes made must be merged back into the original "master" set of source files.

    viff was created to support the copy-merge method. It is surely the most convenient method, but the need to merge files has traditionally been a very, very big problem. For instance, an output from the "diff" program can be used as guidance for merging two files and though this is a help, a diff output is hard to read and each difference is presented with no context. It also still requires manual editing, so the merger needs to work with and switch between two files plus a diff output all at the same time.

    Anyone who has tried this will know that this is a tiresome and tedious task if there are more than just a couple of changes. Also, the risk of introducing bugs (by mistyping, overlooking a change, changing the code the wrong place, etc) is quite high. If two files alone seems hard to merge this way, merging two whole directories can be practically impossible!

    This is where viff comes in. It automates this whole process by running diff on the files, interpret diff's output, and present the differences in a manner suited for easy interactive merging and even editing of the two files. It can viff two entire directories as easy as just two files.

    Of course, viff is not only meant for programmers. It is also very useful for diffing and merging HTML web-pages and all other plain texts.

    Why is viff character-based?

    Many window based programs have lots of fancy, irrelevant features, but often very little real power. They are like James Bond's Aston Martin equipped with a lawnmower engine whereas viff is a Range Rover with a Range Rover engine. In that sense viff can be compared to e.g. grep. grep is not a fancy window based program that will highlight every matching line in a file in a scrollable, mouse-operated window with font options in a menubar. No, grep is plain and simple and therefore it is a delight to use it when you really want to get some work done.

    When you only have to merge two files you are likely to think to yourself: "I'm glad I can merge the files at all". You might be pleased to use an impressive looking program to merge the two files at your own leisure pace. But, when merging several files -- dozens or hundreds -- it rapidly becomes more and more important to use a tool that solves the problem at hand as fast and smoothly as possible. You are not impressed anymore, you just have a job to do.

    Back to top

    Running viff

    viff use diff to perform the actual diffing, and can therefore only compare two files with each other. But unlike diff, viff can make sense of other kind of arguments than just two filenames. These will be described here.

    The simplest invocation of viff is

    viff file1 file2

    viff always start up selecting the changes belonging to the first file specifed (referred to as "file 1" for short) so it is wise to specify the more recent file(s) first.
    To speed things up, viff will process a whole series of files if more than two filenames are given and the first or last refers to a directory. Doing this,

    viff file1 file2 tmp

    will cause viff to compare file1 and file2 to the corresponding files in tmp. Placing the directory first (ie viff tmp file1 file2) will reverse the comparison.
    As another example, the C-files in two entire directories can be compared easily using

    viff version5/*.c version4

    When invoked with two directory names, viff will by itself search the first directory for files. So if you want to compare all the files in the two directories in the example above, you won't even have to specify version5/*, but can simply ask for

    viff version5 version4

    Back to top

    viff options

    viff has several options.

    -h
    Brief describtion of syntax and options.
    -l
    Produce listing. When facing a potentially large viff session it is nice to know if you should take a coffee break before starting: will there be a total of 12 or 683 differences?
    -m
    Monochrome display. Use this to force viff to run in black and white.
    -o options
    Pass options to diff. In the example viff -o -w a1 a2, diff is passed the option -w, telling it to compare sequences of whitespace equal. -o can be specified more than once on the command line and the options will all be passed to diff.
    -p program
    Instead of "diff", use this program to perform the diffing. Use this if diff is either not in your path or that diff is a non-standard diff. In that case you could use e.g. viff -p /usr/you/bin/diff a1 a2.
    -t width
    Set tabulator width. Default is 8. Use this if you are viffing files that use another tabulator width, e.g. 4. The tabulator width can also be set from within viff.
    -V
    Show version info.

    The following options can only be used when viffing a set of files:

    -f filename
    Start viffing at this filename. Use this to resume a viff session that has been quitted.
    -i
    Ignore header (RCS header) difference. If the only difference is in the version control header, the file is skipped; otherwise, viffing starts at the second difference.
    -v
    Be verbose. Without this flag viff is pleasently silent when viffing a set of files: it doesn't stop to tell you about files not found and files with no differences, since normally you don't care about that. If you do, use -v. viff is always verbose when viffing just two single files.
    -x
    Skip generated files. This saves you from viffing files that you don't care about. If you are doing e.g. viff dir1 dir2 and dir1 and dir2 both contain the two files x.i and x.c, then the .i file will be skipped because it is a preprocessed C-file generated from the .c C-source file. The types of generated files that are skipped are:
    • skip C-source files (.c .h) generated from an ASN.1 file (.asn)
    • skip C-source files (.c .h) generated from a Yacc file file (.y)
    • skip preprocessed file (.i) generated from a C-source file (.c)
    • skip compiled file (.elc) generated from an emacs-lisp file (.el)

    You can combine options in the standard Unix fashion, like

    viff -vlf sved.c *.c ../work

    In summary, these are the differences between viffing just two files and viffing a set of files:

    Back to top

    The viff display

    (todo: How are the two files displayed?)

    Trailing whitespace is shown as light blue bullets (for space) and diamonds (for tab) on DOS, and as light blue underscores (for both) on Unix. A line exceeding the screen width will end in a small magenta right arrow on DOS and in a magenta > on Unix.

    Modes in viff

    There are two modes in viff: viffmode and editmode. viff always starts up in viffmode and by pressing Insert you can change into editmode and back into viffmode again. Each mode has its own type of status line.

    Viffmode

    In viffmode the statusline is green and can look like this:

    Viff ** password.c 7/13 11-2 (53+7)

    Viff
    Mode. This tells us that we are in viffmode, not editmode.
    **
    Edited. Shown if the file has been edited by you.
    password.c
    Filename. A filename is only shown if the name of the two files being viffed are the same when their paths are stripped. If you viff file1.c and file2.c, nothing is displayed here, but if you viff /tmp/file1.c against work/sved/file1.c, then file1.c is shown.

    The remainer of the line is specific for viffmode:

    7/13
    Difference count. Show the current diff and the total diffs. In this example we are looking at the 7th difference out of a total of 13.
    11-2
    Difference selections. Show the number of selections from each file. Of the 13 differences in this example, 11 has been chosen from file 1 and only two from file 2.
    (53+7)
    Current difference size. If the current diff spans more lines than fit on the screen, this is shown to inform of how many lines the diff contains. This diff is a rather big one, containing 53 lines from file 1 and just 7 from file 2.

    Editmode

    In editmode the statusline is red and can look like this:

    Edit ** password.c col:7 lin:14/18 char= 0xd 13 015 ^M

    Here, Edit tells us that we now are in editmode, and the ** password.c is described above. The remainer of the line is specific for editmode:

    col:7
    Column. Show the current column
    lin:14/18
    Line. Show the current line. Here we are at the 14th line in file 1 which is the 18th line of file 2. The line refer to the linenumbers in the original files, no matter what editing might have taken place. There are several "lin:" variations:
    • lin:5 is the 5th line in both files
    • lin:new is a new line (a newline inserted in editmode)
    • lin:-/12 is line 12 in file2, which is not present in file 1
    • lin:*14 is a broken 14th line; this is a part of it
    A combination of these examples can also occur.
    char=...
    Character information. When the cursor is over a control character or an 8-bit character, that character's ASCII code is shown in hex, decimal, and octal. Control characters from ^A to ^Z are displayed just like that.

    Back to top

    viff commands

    There is no mouse based controls in viff, so everything is handled via the keyboard. At any time when "F1=help" is displayed in the status line, pressing F1 will bring up a help screen. This includes viffmode, editmode, searchmode, and when being asked questions by viff. The different help screens will list all the commands that you can use in the current mode or situation.

    Commands in viffmode

    Use up/down arrow to move to the previous/next diff and home/end to move to the first/last diff. If the platform supports it you can use the Control and Alt keys in conjunction with these navigation keys to only navigate through differences from file 1 or 2: use e.g. ctrl-up to move to the previous diff from file 1, or alt-end to move to the last diff from file 2.

    At a diff you may use left/right arrow to choose whether to use the text from file 1 or 2 or press Space to toggle the selection. You can also use the parenthesis '(' and ')' to select all texts from file 1 or 2 respectively.

    For more context, use page up/down to move the view a page up or down. This only shifts the view, not the current diff. To bring the current diff into focus again, use '.' (a tribute to NetHack). If the middle line of the current diff is visible the cursor is put there, else it is put in the status line.

    ctrl-s and ctrl-r will do a search (described later).

    By pressing Insert, you can edit the entire text; see the section on edit commands below. Pressing Escape or Insert again exits edit mode.

    Pressing 1 or 2 saves the modified file as either file 1 or file 2 and quits viffing these two files. Pressing 3 saves the modified file into both file 1 and 2. Pressing 4 saves the modified file into a completely new file and clears the modification-flag, but does not quit. Pressing 5 saves all the text exactly as you see it, with viff-inserted lines and delimiters and everything.

    Escape or q quits viffing the two files. Capital Q quits viffing any more files as well. If the modification flag is set, you will be asked to confirm your request to quit. When viff is busy viffing files it is possible to interrupt it in this way too. Here Escape and q ask for confirmation, while Q just quits.

    Pressing < will go back to the previously viffed pair of files, or re-viff the current file if there are no previous viffings. For symmetry, pressing > will go on to the next pair (like q).

    Commands in editmode

    Pressing Insert enters edit mode. The usual arrow movement keys and delete keys apply as well as a few other Emacs-like edit facilities. Use F1 to see them all. Use Escape or Insert to exit.

    To copy text, kill it using ctrl-k and yank the text back at the desired position using ctrl-y. To copy several lines, press ctrl-k several times after one another. This is useful for pasting if you don't want just the text from file 1 or just that from file 2, but rather something from both files.

    ctrl-s and ctrl-r will do a search.

    Searching in the text

    In viff you can search in all the text, both forward (by pressing ctrl-s) and backward (by pressing ctrl-r) and both in viffmode and in editmode. The search can optionally be case sensitive or be a match on whole words only, which is nice for e.g. locating only occurences of variable "w".

    Once you have pressed ctrl-s or ctrl-r, you begin by entering a string to search for. As this string is being entered a match count is shown, helping you to decide when to start the actual search. You can at any time change the search to be case-sensitive (by pressing ctrl-c, for case) and to search for only whole words (by pressing ctrl-w, for word).

    The actual search is begun by pressing either ctrl-s or ctrl-r again (or Return), for searching either forward or backward. The cursor then moves to the first match of the search string in the text window in the given direction. Pressing ctrl-s or ctrl-r again will search for the next match. When there are no more matches a beep will sound. Pressing the search key immediately again will wrap and continue searching.

    Pressing ctrl-g will quit searchmode and go back to where you were when you started searching. Pressing any other key will shift into editmode and input that key.

    The last search string is remembered by viff, so you can repeat a search by pressing the search key twice, e.g. ctrl-s ctrl-s.

    Back to top

    Compiling viff

    viff is based on curses(3). The 16-bit MS-DOS version has been compiled with MSVC and linked with PDcurses v2.2. The 32-bit version has been compiled with djgpp. The 32-bit version is limited only by memory. I have e.g. viffed two 4Mb files with 530,000 lines each and with 175,000 differences without problems.

    Back to top

    Remarks

    Here are a few odds and ends.

    Back to top

    About the author

    viff was written by Richard Nordsted Flamsholt. I'll be glad to receive comments, bug-reports, ideas and suggestions, and other feedback at richard@native.dk.